﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services.Protocols;
using System.Text;
using System.Web.Services;
using CarolLib;

namespace DispatchAssist.WebService
{
    public class ValidationExtension : SoapExtension
    {
        DASoapHeader daheader;
        bool enableLog;

        public override void ProcessMessage(SoapMessage message)
        {
            switch (message.Stage)
            {
                case SoapMessageStage.AfterDeserialize:
                    {
                        Validation(message);
                        if (enableLog)
                        {
                            Log(message);
                        }
                    }
                    break;
                case SoapMessageStage.AfterSerialize:
                    break;
                case SoapMessageStage.BeforeDeserialize:
                    break;
                case SoapMessageStage.BeforeSerialize:
                    break;
                default:
                    break;
            }
        }

        public override Object GetInitializer(Type type)
        {
            return GetType();
        }

        public override Object GetInitializer(LogicalMethodInfo info, SoapExtensionAttribute attribute)
        {
            return ((ValidationAttribute)attribute).EnableLog;
        }

        public override void Initialize(object initializer)
        {
            enableLog = (bool)initializer;
        }

        private void Validation(SoapMessage message)
        {
            bool check = false;

            if (this.daheader == null)
            {
                foreach (SoapHeader header in message.Headers)
                {
                    if (header is DASoapHeader)
                    {
                        this.daheader = (DASoapHeader)header;
                        break;
                    }
                }
            }

            if (daheader == null || daheader.ValidateUser())
            {
                check = true;
            }

            if (!check)
                throw new SoapHeaderException("认证失败", SoapException.ClientFaultCode);
        }

        private void Log(SoapMessage message)
        {
            if (this.daheader == null)
            {
                foreach (SoapHeader header in message.Headers)
                {
                    if (header is DASoapHeader)
                    {
                        this.daheader = (DASoapHeader)header;
                        break;
                    }
                }
            }

            List<string> param = new List<string>();
            int pcount = message.MethodInfo.Parameters.Count();

            for (int i = 0; i < pcount; i++)
            {
                param.Add(message.GetInParameterValue(i).ToString());
            }

            string desc;
            if (!CacheHelper.TryGet<string>(message.MethodInfo.Name, out desc))
            {
                desc = GetDescriptionAttribute(message.MethodInfo);
                CacheHelper.Insert(message.MethodInfo.Name, desc, 36000);
            }

            try
            {
                daheader.Log(daheader.UserId, daheader.SeatId[0], desc, param.ToArray());
            }
            catch (Exception e)
            {
                CarolLib.Log.Instance.Warn("Error during daheader.Log", e);
            }
        }

        private string GetDescriptionAttribute(LogicalMethodInfo method)
        {
            string description = "";
            foreach (Attribute attr in method.GetCustomAttributes(typeof(WebMethodAttribute)))
            {
                System.Web.Services.WebMethodAttribute wma = attr
                                         as System.Web.Services.WebMethodAttribute;
                if (wma != null)
                {
                    description = wma.Description;
                    break;
                }
            }
            return description;
        }
    }
}